package com.wang.project.service.impl;

import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.wang.openApiclientsdk.client.OpenApiClient;
import com.wang.project.common.DeleteRequest;
import com.wang.project.common.ErrorCode;
import com.wang.project.common.idRequest;
import com.wang.project.constant.CommonConstant;
import com.wang.project.constant.InterfaceConstant;
import com.wang.project.constant.UserConstant;
import com.wang.project.exception.BusinessException;
import com.wang.project.mapper.InterfaceInfoMapper;
import com.wang.project.model.dto.interfaceInfo.InterfaceInfoAddRequest;
import com.wang.project.model.dto.interfaceInfo.InterfaceInfoInvokeRequest;
import com.wang.project.model.dto.interfaceInfo.InterfaceInfoQueryRequest;
import com.wang.project.model.dto.interfaceInfo.InterfaceInfoUpdateRequest;
import com.wang.project.model.entity.*;
import com.wang.project.model.enums.ApprovalStatusEnum;
import com.wang.project.model.enums.InterfaceInfoStatusEnum;
import com.wang.project.model.vo.interfaceInfo.InterfaceInfoVO;
import com.wang.project.service.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author 胡歌的腿毛
 * @description 针对表【interface_info(接口信息表)】的数据库操作Service实现
 * @createDate 2023-05-06 15:05:47
 */
@Service
@Slf4j
public class InterfaceInfoServiceImpl extends ServiceImpl<InterfaceInfoMapper, InterfaceInfo> implements InterfaceInfoService {

    @Resource
    private UserService userService;

    @Resource
    private UserKeyService userKeyService;

    @Resource
    private UserInterfaceInfoService userInterfaceInfoService;

    @Resource
    private ApprovalService approvalService;

    /**
     * 校验参数
     *
     * @param interfaceInfo
     * @param add
     */
    @Override
    public void validInterfaceInfo(InterfaceInfo interfaceInfo, boolean add) {
        if (interfaceInfo == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        String name = interfaceInfo.getName();

        // 创建时，所有参数必须非空
        if (add) {
            if (StringUtils.isAnyBlank(name)) {
                throw new BusinessException(ErrorCode.PARAMS_ERROR, "参数必须非空");
            }
        }
        if (StringUtils.isNotBlank(name) && name.length() > 50) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "名称过长,不能超过50个字符");
        }

    }

    /**
     * 检验测试接口方法的参数 权限 有无接口调用次数等
     *
     * @param interfaceInfoInvokeRequest
     * @param request
     * @return
     */
    @Override
    public Boolean validTestInterface(InterfaceInfoInvokeRequest interfaceInfoInvokeRequest, HttpServletRequest request) {
        if (interfaceInfoInvokeRequest == null || interfaceInfoInvokeRequest.getId() <= 0) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        //判断接口是否存在
        long id = interfaceInfoInvokeRequest.getId();
        InterfaceInfo oldInterfaceInfo = this.getById(id);
        if (oldInterfaceInfo == null) {
            log.info("validTestInterface oldInterfaceInfo is null");
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR);
        }
        if (oldInterfaceInfo.getStatus() == InterfaceInfoStatusEnum.OFFLINE.getValue()) {
            log.info("validTestInterface oldInterfaceInfo status is close");
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "接口已关闭");
        }

        User loginUser = userService.getLoginUser(request);

        //判断是否还有调用次数
        QueryWrapper<UserInterfaceInfo> userInterfaceInfoQueryWrapper = new QueryWrapper<>();
        userInterfaceInfoQueryWrapper.eq("interfaceId", oldInterfaceInfo.getId());
        userInterfaceInfoQueryWrapper.eq("userId", loginUser.getId());
        UserInterfaceInfo userInterfaceInfo = userInterfaceInfoService.getOne(userInterfaceInfoQueryWrapper);
        if (userInterfaceInfo.getLeftNum() <= 0) {
            log.info("validTestInterface 测试接口 调用次数已用完");
            return false;
        }


        QueryWrapper<UserKey> userKeyQueryWrapper = new QueryWrapper<>();
        userKeyQueryWrapper.eq("user_id", loginUser.getId());
        UserKey userKey = userKeyService.getOne(userKeyQueryWrapper);
        //校验身份
        String accessKey = loginUser.getAccessKey();
        String secretKey = loginUser.getSecretKey();
        String resultAccessKey = userKey.getAccessKey();
        String resultSecretKey = userKey.getSecretKey();
        if ((!accessKey.equals(resultAccessKey)) || (!secretKey.equals(resultSecretKey))) {
            log.info("validTestInterface 校验ak sk错误  accessKey: {} , secretKey: {}", accessKey, secretKey);
            return false;
        }
        return true;
    }


    /**
     * 创建接口
     *
     * @param interfaceInfoAddRequest
     * @param request
     * @return
     */
    @Override
    public Boolean addInterfaceInfo(InterfaceInfoAddRequest interfaceInfoAddRequest, HttpServletRequest request) {
        if (interfaceInfoAddRequest == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        log.info("InterfaceInfoServiceImpl addInterfaceInfo interfaceInfoAddRequest:{}", JSONUtil.toJsonStr(interfaceInfoAddRequest));
        InterfaceInfo interfaceInfo = new InterfaceInfo();
        BeanUtils.copyProperties(interfaceInfoAddRequest, interfaceInfo);
        // 校验
        this.validInterfaceInfo(interfaceInfo, true);
        User loginUser = userService.getLoginUser(request);

        //判断是管理员还是用户自己创建接口
        if (userService.isAdmin(request)) {
            //管理员操作，直接发布
            Long loginUserId = loginUser.getId();
            interfaceInfo.setUserId(loginUserId);
            interfaceInfo.setStatus(InterfaceConstant.STATUS); //管理员发布接口状态就为开启
            boolean result = this.save(interfaceInfo);
            if (!result) {
                throw new BusinessException(ErrorCode.OPERATION_ERROR);
            }
            return result;
        }

        //用户自己创建接口 进行审核区域
        Approval approval = new Approval();
        BeanUtils.copyProperties(interfaceInfoAddRequest, approval);
        approval.setUserId(loginUser.getId());
        approval.setApprovalStatus(ApprovalStatusEnum.APPROVALING.getValue());
        approval.setIntegral(interfaceInfoAddRequest.getIntegral());
        log.info("InterfaceInfoServiceImpl addInterfaceInfo save approval:{}", JSONUtil.toJsonStr(approval));
        return approvalService.save(approval);
        //通知管理员进行审核
    }

    /**
     * 删除接口
     * 管理员可以删除接口，用户自己发布的接口，用户也可以自己删除
     *
     * @param deleteRequest
     * @param request
     * @return
     */
    @Override
    public Boolean deleteInterfaceInfo(DeleteRequest deleteRequest, HttpServletRequest request) {
        if (deleteRequest == null || deleteRequest.getId() <= 0) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        User user = userService.getLoginUser(request);
        long id = deleteRequest.getId();
        // 判断是否存在
        InterfaceInfo oldInterfaceInfo = this.getById(id);
        if (oldInterfaceInfo == null) {
            log.info("InterfaceInfoServiceImpl deleteInterfaceInfo oldInterfaceInfo is null");
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR);
        }
        log.info("InterfaceInfoServiceImpl deleteInterfaceInfo InterfaceInfo:{}", JSONUtil.toJsonStr(oldInterfaceInfo));
        // 仅本人或管理员可删除
        if (!oldInterfaceInfo.getUserId().equals(user.getId()) && !userService.isAdmin(request)) {
            log.info("InterfaceInfoServiceImpl deleteInterfaceInfo NO AUTH ERROR");
            throw new BusinessException(ErrorCode.NO_AUTH_ERROR);
        }
        return this.removeById(id);
    }

    /**
     * 更新接口
     * 仅本人或管理员可修改
     *
     * @param interfaceInfoUpdateRequest
     * @param request
     * @return
     */
    @Override
    public Boolean updateInterfaceInfo(InterfaceInfoUpdateRequest interfaceInfoUpdateRequest, HttpServletRequest request) {
        InterfaceInfo interfaceInfo = new InterfaceInfo();
        BeanUtils.copyProperties(interfaceInfoUpdateRequest, interfaceInfo);
        // 参数校验
        this.validInterfaceInfo(interfaceInfo, false);
        User user = userService.getLoginUser(request);
        long id = interfaceInfoUpdateRequest.getId();
        // 判断是否存在
        InterfaceInfo oldInterfaceInfo = this.getById(id);
        if (oldInterfaceInfo == null) {
            log.info("InterfaceInfoServiceImpl updateInterfaceInfo oldInterfaceInfo is null");
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR);
        }
        log.info("InterfaceInfoServiceImpl updateInterfaceInfo InterfaceInfo:{}", JSONUtil.toJsonStr(oldInterfaceInfo));
        // 仅本人或管理员可修改
        if (!oldInterfaceInfo.getUserId().equals(user.getId()) && !userService.isAdmin(request)) {
            log.info("InterfaceInfoServiceImpl updateInterfaceInfo NO AUTH ERROR");
            throw new BusinessException(ErrorCode.NO_AUTH_ERROR);
        }
        return this.updateById(interfaceInfo);
    }

    /**
     * 管理员获取所有接口信息
     *
     * @param interfaceInfoQueryRequest
     * @return
     */
    @Override
    public List<InterfaceInfo> listInterfaceInfo(InterfaceInfoQueryRequest interfaceInfoQueryRequest) {
        InterfaceInfo interfaceInfoQuery = new InterfaceInfo();
        if (interfaceInfoQueryRequest != null) {
            BeanUtils.copyProperties(interfaceInfoQueryRequest, interfaceInfoQuery);
        }
        QueryWrapper<InterfaceInfo> queryWrapper = new QueryWrapper<>(interfaceInfoQuery);
        List<InterfaceInfo> interfaceInfoList = this.list(queryWrapper);
        return interfaceInfoList;
    }


    /**
     * 获取用户申请的接口和自己创建的接口
     *
     * @param interfaceInfoQueryRequest
     * @param request
     * @return
     */
    @Override
    public List<InterfaceInfoVO> getUserInterfaceInfoList(InterfaceInfoQueryRequest interfaceInfoQueryRequest, HttpServletRequest request) {
        log.info("InterfaceInfoServiceImpl getUserInterfaceInfoList interfaceInfoQueryRequest:{}", JSONUtil.toJsonStr(interfaceInfoQueryRequest));
        User loginUser = userService.getLoginUser(request);

        //获取自己创建的接口
        QueryWrapper<InterfaceInfo> interfaceInfoQueryWrapper = new QueryWrapper<>();
        interfaceInfoQueryWrapper.eq("userId", loginUser.getId());
        List<InterfaceInfo> myInterfaceList = this.list(interfaceInfoQueryWrapper);
        log.info("InterfaceInfoServiceImpl getUserInterfaceInfoList myInterfaceList:{}", JSONUtil.toJsonStr(myInterfaceList));

        //从userInterface表中获取自己申请到的接口
        QueryWrapper<UserInterfaceInfo> userInterfaceInfoQueryWrapper = new QueryWrapper<>();
        userInterfaceInfoQueryWrapper.eq("userId", loginUser.getId());
        List<UserInterfaceInfo> userInterfaceInfos = userInterfaceInfoService.list(userInterfaceInfoQueryWrapper);
        List<Long> myInterfaceIds = userInterfaceInfos.stream().map(UserInterfaceInfo::getInterfaceInfoId).collect(Collectors.toList());
        List<InterfaceInfo> myApplyInterfaceInfoList = this.listByIds(myInterfaceIds);
        log.info("InterfaceInfoServiceImpl getUserInterfaceInfoList myApplyInterfaceInfoList:{}", JSONUtil.toJsonStr(myApplyInterfaceInfoList));

        //组装list
        myApplyInterfaceInfoList.addAll(myInterfaceList);
        List<InterfaceInfoVO> result = myApplyInterfaceInfoList.stream().map(item -> {
            InterfaceInfoVO interfaceInfoVO = new InterfaceInfoVO();
            BeanUtils.copyProperties(item, interfaceInfoVO);
            return interfaceInfoVO;
        }).collect(Collectors.toList());
        return result;
    }

    /**
     * 分页获取接口信息列表
     *
     * @param interfaceInfoQueryRequest
     * @param request
     * @return
     */
    @Override
    public Page<InterfaceInfo> listInterfaceInfoByPage(InterfaceInfoQueryRequest interfaceInfoQueryRequest, HttpServletRequest request) {
        InterfaceInfo interfaceInfoQuery = new InterfaceInfo();
        BeanUtils.copyProperties(interfaceInfoQueryRequest, interfaceInfoQuery);
        long current = interfaceInfoQueryRequest.getCurrent();
        long size = interfaceInfoQueryRequest.getPageSize();
        String sortField = interfaceInfoQueryRequest.getSortField();
        String sortOrder = interfaceInfoQueryRequest.getSortOrder();
        String description = interfaceInfoQuery.getDescription();
        // content 需支持模糊搜索
        interfaceInfoQuery.setDescription(null);
        // 限制爬虫
        if (size > 50) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        QueryWrapper<InterfaceInfo> queryWrapper = new QueryWrapper<>(interfaceInfoQuery);
        queryWrapper.like(StringUtils.isNotBlank(description), "description", description);
        queryWrapper.orderBy(StringUtils.isNotBlank(sortField), sortOrder.equals(CommonConstant.SORT_ORDER_ASC), sortField);
        Page<InterfaceInfo> interfaceInfoPage = this.page(new Page<>(current, size), queryWrapper);
        return interfaceInfoPage;
    }

    /**
     * 上线接口
     *
     * @param idRequest
     * @param request
     * @return
     */
    @Override
    public Boolean onlineInterfaceInfo(idRequest idRequest, HttpServletRequest request) {
//        //判断接口是否存在
//        long id = idRequest.getId();
//        InterfaceInfo oldInterfaceInfo = this.getById(id);
//        if (oldInterfaceInfo == null) {
//            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR);
//        }
//
//        //判断接口是否可用，使用yuApiClient调用测试是否可用
//        // todo 这里并没有用到传过来的地址的id去测试，需要修改判断接口是否可用这一方法
//        // todo 应该是拿到这个id数据的地址去测试，所以这里还需要去修改yuApiClient这一sdk
//        com.wang.openApiClient.model.User user = new com.wang.openApiClient.model.User();
//        user.setUsername("test");
//        String username = yuApiClient.getUsernameByPost(user);
//        if (StringUtils.isBlank(username)) {
//            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "接口验证失败");
//        }
//
//        //修改接口数据库中的状态字段为1
//        InterfaceInfo interfaceInfo = new InterfaceInfo();
//        interfaceInfo.setId(id);
//        interfaceInfo.setStatus(InterfaceInfoStatusEnum.ONLINE.getValue());
//        return this.updateById(interfaceInfo);
        return false;
    }

    /**
     * 下线接口  通过接口id
     *
     * @param idRequest 接口id
     * @param request
     * @return
     */
    @Override
    public Boolean offlineInterfaceInfo(idRequest idRequest, HttpServletRequest request) {
        //判断接口是否存在
        long id = idRequest.getId();
        InterfaceInfo oldInterfaceInfo = this.getById(id);
        if (oldInterfaceInfo == null) {
            log.info("InterfaceInfoServiceImpl offlineInterfaceInfo oldInterfaceInfo is null");
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR);
        }

        //修改接口数据库中的状态字段为1
        InterfaceInfo interfaceInfo = new InterfaceInfo();
        interfaceInfo.setId(id);
        interfaceInfo.setStatus(InterfaceInfoStatusEnum.OFFLINE.getValue());
        log.info("InterfaceInfoServiceImpl offlineInterfaceInfo offline interfaceInfo:{}", JSONUtil.toJsonStr(interfaceInfo));
        return this.updateById(interfaceInfo);
    }


}




